1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.print;
27
28 import javax.print.attribute.*;
29 import javax.print.attribute.standard.*;
30 import javax.print.DocFlavor;
31 import javax.print.DocPrintJob;
32 import javax.print.PrintService;
33 import javax.print.ServiceUIFactory;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.Locale;
37 import java.util.Date;
38 import java.util.Arrays;
39 import java.security.AccessController;
40 import java.security.PrivilegedActionException;
41 import java.security.PrivilegedExceptionAction;
42 import javax.print.event.PrintServiceAttributeListener;
43
44 import java.net.URI;
45 import java.net.URISyntaxException;
46 import java.net.URL;
47 import java.net.HttpURLConnection;
48 import java.io.File;
49 import java.io.InputStream;
50 import java.io.OutputStream;
51 import java.io.OutputStreamWriter;
52 import java.io.DataInputStream;
53 import java.io.ByteArrayOutputStream;
54 import java.io.ByteArrayInputStream;
55 import java.io.BufferedReader;
56 import java.io.InputStreamReader;
57 import java.nio.charset.Charset;
58
59 import java.util.Iterator;
60 import java.util.HashSet;
61
62
63 public class IPPPrintService implements PrintService, SunPrinterJobService {
64
65 public static final boolean debugPrint;
66 private static final String debugPrefix = "IPPPrintService>> ";
67 protected static void debug_println(String str) {
68 if (debugPrint) {
69 System.out.println(str);
70 }
71 }
72
73 private static final String FORCE_PIPE_PROP = "sun.print.ippdebug";
74
75 static {
76 String debugStr =
77 (String)java.security.AccessController.doPrivileged(
78 new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP));
79
80 debugPrint = "true".equalsIgnoreCase(debugStr);
81 }
82
83 private String printer;
84 private URI myURI;
85 private URL myURL;
86 transient private ServiceNotifier notifier = null;
87
88 private static int MAXCOPIES = 1000;
89 private static short MAX_ATTRIBUTE_LENGTH = 255;
90
91 private CUPSPrinter cps;
92 private HttpURLConnection urlConnection = null;
93 private DocFlavor[] supportedDocFlavors;
94 private Class[] supportedCats;
95 private MediaTray[] mediaTrays;
96 private MediaSizeName[] mediaSizeNames;
97 private CustomMediaSizeName[] customMediaSizeNames;
98 private int defaultMediaIndex;
99 private boolean isCupsPrinter;
100 private boolean init;
101 private Boolean isPS;
102 private HashMap getAttMap;
103 private boolean pngImagesAdded = false;
104 private boolean gifImagesAdded = false;
105 private boolean jpgImagesAdded = false;
106
107
108
109
110
111 private static final byte STATUSCODE_SUCCESS = 0x00;
112
113
114
115
116
117
118 private static final byte GRPTAG_OP_ATTRIBUTES = 0x01;
119
120 private static final byte GRPTAG_JOB_ATTRIBUTES = 0x02;
121
122 private static final byte GRPTAG_PRINTER_ATTRIBUTES = 0x04;
123
124 private static final byte GRPTAG_END_ATTRIBUTES = 0x03;
125
126
127
128
129
130 public static final String OP_GET_ATTRIBUTES = "000B";
131
132 public static final String OP_CUPS_GET_DEFAULT = "4001";
133
134 public static final String OP_CUPS_GET_PRINTERS = "4002";
135
136
137
138
139
140
141 private static Object[] printReqAttribDefault = {
142 Chromaticity.COLOR,
143 new Copies(1),
144 Fidelity.FIDELITY_FALSE,
145 Finishings.NONE,
146
147
148
149
150
151 new JobName("", Locale.getDefault()),
152
153 JobSheets.NONE,
154 (Media)MediaSizeName.NA_LETTER,
155
156
157 new NumberUp(1),
158 OrientationRequested.PORTRAIT,
159 new PageRanges(1),
160
161
162
163
164 new RequestingUserName("", Locale.getDefault()),
165
166 Sides.ONE_SIDED,
167 };
168
169
170
171
172
173
174 private static Object[][] serviceAttributes = {
175 {ColorSupported.class, "color-supported"},
176 {PagesPerMinute.class, "pages-per-minute"},
177 {PagesPerMinuteColor.class, "pages-per-minute-color"},
178 {PDLOverrideSupported.class, "pdl-override-supported"},
179 {PrinterInfo.class, "printer-info"},
180 {PrinterIsAcceptingJobs.class, "printer-is-accepting-jobs"},
181 {PrinterLocation.class, "printer-location"},
182 {PrinterMakeAndModel.class, "printer-make-and-model"},
183 {PrinterMessageFromOperator.class, "printer-message-from-operator"},
184 {PrinterMoreInfo.class, "printer-more-info"},
185 {PrinterMoreInfoManufacturer.class, "printer-more-info-manufacturer"},
186 {PrinterName.class, "printer-name"},
187 {PrinterState.class, "printer-state"},
188 {PrinterStateReasons.class, "printer-state-reasons"},
189 {PrinterURI.class, "printer-uri"},
190 {QueuedJobCount.class, "queued-job-count"}
191 };
192
193
194
195
196
197
198
199
200 private static DocFlavor[] appPDF = {
201 DocFlavor.BYTE_ARRAY.PDF,
202 DocFlavor.INPUT_STREAM.PDF,
203 DocFlavor.URL.PDF
204 };
205
206
207 private static DocFlavor[] appPostScript = {
208 DocFlavor.BYTE_ARRAY.POSTSCRIPT,
209 DocFlavor.INPUT_STREAM.POSTSCRIPT,
210 DocFlavor.URL.POSTSCRIPT
211 };
212
213
214 private static DocFlavor[] appOctetStream = {
215 DocFlavor.BYTE_ARRAY.AUTOSENSE,
216 DocFlavor.INPUT_STREAM.AUTOSENSE,
217 DocFlavor.URL.AUTOSENSE
218 };
219
220
221 private static DocFlavor[] textPlain = {
222 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8,
223 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16,
224 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE,
225 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE,
226 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII,
227 DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8,
228 DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16,
229 DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE,
230 DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE,
231 DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII,
232 DocFlavor.URL.TEXT_PLAIN_UTF_8,
233 DocFlavor.URL.TEXT_PLAIN_UTF_16,
234 DocFlavor.URL.TEXT_PLAIN_UTF_16BE,
235 DocFlavor.URL.TEXT_PLAIN_UTF_16LE,
236 DocFlavor.URL.TEXT_PLAIN_US_ASCII,
237 DocFlavor.CHAR_ARRAY.TEXT_PLAIN,
238 DocFlavor.STRING.TEXT_PLAIN,
239 DocFlavor.READER.TEXT_PLAIN
240 };
241
242 private static DocFlavor[] textPlainHost = {
243 DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST,
244 DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,
245 DocFlavor.URL.TEXT_PLAIN_HOST
246 };
247
248
249 private static DocFlavor[] imageJPG = {
250 DocFlavor.BYTE_ARRAY.JPEG,
251 DocFlavor.INPUT_STREAM.JPEG,
252 DocFlavor.URL.JPEG
253 };
254
255
256 private static DocFlavor[] imageGIF = {
257 DocFlavor.BYTE_ARRAY.GIF,
258 DocFlavor.INPUT_STREAM.GIF,
259 DocFlavor.URL.GIF
260 };
261
262
263 private static DocFlavor[] imagePNG = {
264 DocFlavor.BYTE_ARRAY.PNG,
265 DocFlavor.INPUT_STREAM.PNG,
266 DocFlavor.URL.PNG
267 };
268
269
270 private static DocFlavor[] textHtml = {
271 DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_8,
272 DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16,
273 DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16BE,
274 DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16LE,
275 DocFlavor.BYTE_ARRAY.TEXT_HTML_US_ASCII,
276 DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_8,
277 DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16,
278 DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16BE,
279 DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16LE,
280 DocFlavor.INPUT_STREAM.TEXT_HTML_US_ASCII,
281 DocFlavor.URL.TEXT_HTML_UTF_8,
282 DocFlavor.URL.TEXT_HTML_UTF_16,
283 DocFlavor.URL.TEXT_HTML_UTF_16BE,
284 DocFlavor.URL.TEXT_HTML_UTF_16LE,
285 DocFlavor.URL.TEXT_HTML_US_ASCII,
286
287
288
289
290
291
292
293 };
294
295 private static DocFlavor[] textHtmlHost = {
296 DocFlavor.BYTE_ARRAY.TEXT_HTML_HOST,
297 DocFlavor.INPUT_STREAM.TEXT_HTML_HOST,
298 DocFlavor.URL.TEXT_HTML_HOST,
299 };
300
301
302
303 private static DocFlavor[] appPCL = {
304 DocFlavor.BYTE_ARRAY.PCL,
305 DocFlavor.INPUT_STREAM.PCL,
306 DocFlavor.URL.PCL
307 };
308
309
310
311 private static Object[] allDocFlavors = {
312 appPDF, appPostScript, appOctetStream,
313 textPlain, imageJPG, imageGIF, imagePNG,
314 textHtml, appPCL,
315 };
316
317
318 IPPPrintService(String name, URL url) {
319 if ((name == null) || (url == null)){
320 throw new IllegalArgumentException("null uri or printer name");
321 }
322 printer = name;
323 supportedDocFlavors = null;
324 supportedCats = null;
325 mediaSizeNames = null;
326 customMediaSizeNames = null;
327 mediaTrays = null;
328 myURL = url;
329 cps = null;
330 isCupsPrinter = false;
331 init = false;
332 defaultMediaIndex = -1;
333
334 String host = myURL.getHost();
335 if (host!=null && host.equals(CUPSPrinter.getServer())) {
336 isCupsPrinter = true;
337 try {
338 myURI = new URI("ipp://"+host+
339 "/printers/"+printer);
340 debug_println(debugPrefix+"IPPPrintService myURI : "+myURI);
341 } catch (java.net.URISyntaxException e) {
342 throw new IllegalArgumentException("invalid url");
343 }
344 }
345 }
346
347
348 IPPPrintService(String name, String uriStr, boolean isCups) {
349 if ((name == null) || (uriStr == null)){
350 throw new IllegalArgumentException("null uri or printer name");
351 }
352 printer = name;
353 supportedDocFlavors = null;
354 supportedCats = null;
355 mediaSizeNames = null;
356 customMediaSizeNames = null;
357 mediaTrays = null;
358 cps = null;
359 init = false;
360 defaultMediaIndex = -1;
361 try {
362 myURL =
363 new URL(uriStr.replaceFirst("ipp", "http"));
364 } catch (Exception e) {
365 IPPPrintService.debug_println(debugPrefix+
366 " IPPPrintService, myURL="+
367 myURL+" Exception= "+
368 e);
369 }
370
371 isCupsPrinter = isCups;
372 try {
373 myURI = new URI(uriStr);
374 debug_println(debugPrefix+"IPPPrintService myURI : "+myURI);
375 } catch (java.net.URISyntaxException e) {
376 throw new IllegalArgumentException("invalid uri");
377 }
378 }
379
380
381
382
383
384
385
386
387 private void initAttributes() {
388 if (!init) {
389
390 customMediaSizeNames = new CustomMediaSizeName[0];
391
392 if ((urlConnection = getIPPConnection(myURL)) == null) {
393 mediaSizeNames = new MediaSizeName[0];
394 mediaTrays = new MediaTray[0];
395 debug_println(debugPrefix+"initAttributes, NULL urlConnection ");
396 init = true;
397 return;
398 }
399
400
401 opGetAttributes();
402
403 if (isCupsPrinter) {
404
405
406
407
408
409
410 try {
411 cps = new CUPSPrinter(printer);
412 mediaSizeNames = cps.getMediaSizeNames();
413 mediaTrays = cps.getMediaTrays();
414 customMediaSizeNames = cps.getCustomMediaSizeNames();
415 urlConnection.disconnect();
416 init = true;
417 return;
418 } catch (Exception e) {
419 IPPPrintService.debug_println(debugPrefix+
420 "initAttributes, error creating CUPSPrinter e="+e);
421 }
422 }
423
424
425 Media[] allMedia = (Media[])getSupportedMedia();
426 ArrayList sizeList = new ArrayList();
427 ArrayList trayList = new ArrayList();
428 for (int i=0; i<allMedia.length; i++) {
429 if (allMedia[i] instanceof MediaSizeName) {
430 sizeList.add(allMedia[i]);
431 } else if (allMedia[i] instanceof MediaTray) {
432 trayList.add(allMedia[i]);
433 }
434 }
435
436 if (sizeList != null) {
437 mediaSizeNames = new MediaSizeName[sizeList.size()];
438 mediaSizeNames = (MediaSizeName[])sizeList.toArray(
439 mediaSizeNames);
440 }
441 if (trayList != null) {
442 mediaTrays = new MediaTray[trayList.size()];
443 mediaTrays = (MediaTray[])trayList.toArray(
444 mediaTrays);
445 }
446 urlConnection.disconnect();
447
448 init = true;
449 }
450 }
451
452
453 public DocPrintJob createPrintJob() {
454 SecurityManager security = System.getSecurityManager();
455 if (security != null) {
456 security.checkPrintJobAccess();
457 }
458
459 return new UnixPrintJob(this);
460 }
461
462
463 public synchronized Object
464 getSupportedAttributeValues(Class<? extends Attribute> category,
465 DocFlavor flavor,
466 AttributeSet attributes)
467 {
468 if (category == null) {
469 throw new NullPointerException("null category");
470 }
471 if (!Attribute.class.isAssignableFrom(category)) {
472 throw new IllegalArgumentException(category +
473 " does not implement Attribute");
474 }
475 if (flavor != null) {
476 if (!isDocFlavorSupported(flavor)) {
477 throw new IllegalArgumentException(flavor +
478 " is an unsupported flavor");
479 } else if (isAutoSense(flavor)) {
480 return null;
481 }
482
483 }
484
485 if (!isAttributeCategorySupported(category)) {
486 return null;
487 }
488
489
490 if (!isDestinationSupported(flavor, attributes)) {
491 return null;
492 }
493
494 initAttributes();
495
496
497 if ((category == Copies.class) ||
498 (category == CopiesSupported.class)) {
499 if (flavor == null ||
500 !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
501 flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
502 flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
503 CopiesSupported cs = new CopiesSupported(1, MAXCOPIES);
504 AttributeClass attribClass = (getAttMap != null) ?
505 (AttributeClass)getAttMap.get(cs.getName()) : null;
506 if (attribClass != null) {
507 int[] range = attribClass.getIntRangeValue();
508 cs = new CopiesSupported(range[0], range[1]);
509 }
510 return cs;
511 } else {
512 return null;
513 }
514 } else if (category == Chromaticity.class) {
515 if (flavor == null ||
516 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
517 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
518 !isIPPSupportedImages(flavor.getMimeType())) {
519 Chromaticity[]arr = new Chromaticity[1];
520 arr[0] = Chromaticity.COLOR;
521 return (arr);
522 } else {
523 return null;
524 }
525 } else if (category == Destination.class) {
526 if (flavor == null ||
527 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
528 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
529 try {
530 return new Destination((new File("out.ps")).toURI());
531 } catch (SecurityException se) {
532 try {
533 return new Destination(new URI("file:out.ps"));
534 } catch (URISyntaxException e) {
535 return null;
536 }
537 }
538 }
539 return null;
540 } else if (category == Fidelity.class) {
541 Fidelity []arr = new Fidelity[2];
542 arr[0] = Fidelity.FIDELITY_FALSE;
543 arr[1] = Fidelity.FIDELITY_TRUE;
544 return arr;
545 } else if (category == Finishings.class) {
546 AttributeClass attribClass = (getAttMap != null) ?
547 (AttributeClass)getAttMap.get("finishings-supported")
548 : null;
549 if (attribClass != null) {
550 int[] finArray = attribClass.getArrayOfIntValues();
551 if ((finArray != null) && (finArray.length > 0)) {
552 Finishings[] finSup = new Finishings[finArray.length];
553 for (int i=0; i<finArray.length; i++) {
554 finSup[i] = Finishings.NONE;
555 Finishings[] fAll = (Finishings[])
556 (new ExtFinishing(100)).getAll();
557 for (int j=0; j<fAll.length; j++) {
558 if (finArray[i] == fAll[j].getValue()) {
559 finSup[i] = fAll[j];
560 break;
561 }
562 }
563 }
564 return finSup;
565 }
566 }
567 } else if (category == JobName.class) {
568 return new JobName("Java Printing", null);
569 } else if (category == JobSheets.class) {
570 JobSheets arr[] = new JobSheets[2];
571 arr[0] = JobSheets.NONE;
572 arr[1] = JobSheets.STANDARD;
573 return arr;
574
575 } else if (category == Media.class) {
576 Media[] allMedia = new Media[mediaSizeNames.length+
577 mediaTrays.length];
578
579 for (int i=0; i<mediaSizeNames.length; i++) {
580 allMedia[i] = mediaSizeNames[i];
581 }
582
583 for (int i=0; i<mediaTrays.length; i++) {
584 allMedia[i+mediaSizeNames.length] = mediaTrays[i];
585 }
586
587 if (allMedia.length == 0) {
588 allMedia = new Media[1];
589 allMedia[0] = (Media)getDefaultAttributeValue(Media.class);
590 }
591
592 return allMedia;
593 } else if (category == MediaPrintableArea.class) {
594 MediaPrintableArea[] mpas = null;
595 if (cps != null) {
596 mpas = cps.getMediaPrintableArea();
597 }
598
599 if (mpas == null) {
600 mpas = new MediaPrintableArea[1];
601 mpas[0] = (MediaPrintableArea)
602 getDefaultAttributeValue(MediaPrintableArea.class);
603 }
604
605 if ((attributes == null) || (attributes.size() == 0)) {
606 ArrayList<MediaPrintableArea> printableList =
607 new ArrayList<MediaPrintableArea>();
608
609 for (int i=0; i<mpas.length; i++) {
610 if (mpas[i] != null) {
611 printableList.add(mpas[i]);
612 }
613 }
614 if (printableList.size() > 0) {
615 mpas = new MediaPrintableArea[printableList.size()];
616 printableList.toArray(mpas);
617 }
618 return mpas;
619 }
620
621 int match = -1;
622 Media media = (Media)attributes.get(Media.class);
623 if (media != null && media instanceof MediaSizeName) {
624 MediaSizeName msn = (MediaSizeName)media;
625
626
627
628 if (mediaSizeNames.length == 0 &&
629 msn.equals(getDefaultAttributeValue(Media.class))) {
630
631 return mpas;
632 }
633
634 for (int i=0; i<mediaSizeNames.length; i++) {
635 if (msn.equals(mediaSizeNames[i])) {
636 match = i;
637 }
638 }
639 }
640
641 if (match == -1) {
642 return null;
643 } else {
644 MediaPrintableArea []arr = new MediaPrintableArea[1];
645 arr[0] = mpas[match];
646 return arr;
647 }
648 } else if (category == NumberUp.class) {
649 AttributeClass attribClass = (getAttMap != null) ?
650 (AttributeClass)getAttMap.get("number-up-supported") : null;
651 if (attribClass != null) {
652 int[] values = attribClass.getArrayOfIntValues();
653 if (values != null) {
654 NumberUp[] nUp = new NumberUp[values.length];
655 for (int i=0; i<values.length; i++) {
656 nUp[i] = new NumberUp(values[i]);
657 }
658 return nUp;
659 } else {
660 return null;
661 }
662 }
663 } else if (category == OrientationRequested.class) {
664 if ((flavor != null) &&
665 (flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
666 flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
667 flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
668 return null;
669 }
670
671 boolean revPort = false;
672 OrientationRequested[] orientSup = null;
673
674 AttributeClass attribClass = (getAttMap != null) ?
675 (AttributeClass)getAttMap.get("orientation-requested-supported")
676 : null;
677 if (attribClass != null) {
678 int[] orientArray = attribClass.getArrayOfIntValues();
679 if ((orientArray != null) && (orientArray.length > 0)) {
680 orientSup =
681 new OrientationRequested[orientArray.length];
682 for (int i=0; i<orientArray.length; i++) {
683 switch (orientArray[i]) {
684 default:
685 case 3 :
686 orientSup[i] = OrientationRequested.PORTRAIT;
687 break;
688 case 4:
689 orientSup[i] = OrientationRequested.LANDSCAPE;
690 break;
691 case 5:
692 orientSup[i] =
693 OrientationRequested.REVERSE_LANDSCAPE;
694 break;
695 case 6:
696 orientSup[i] =
697 OrientationRequested.REVERSE_PORTRAIT;
698 revPort = true;
699 break;
700 }
701 }
702 }
703 }
704 if (flavor == null ||
705 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
706 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
707
708 if (revPort && flavor == null) {
709 OrientationRequested []orSup = new OrientationRequested[4];
710 orSup[0] = OrientationRequested.PORTRAIT;
711 orSup[1] = OrientationRequested.LANDSCAPE;
712 orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
713 orSup[3] = OrientationRequested.REVERSE_PORTRAIT;
714 return orSup;
715 } else {
716 OrientationRequested []orSup = new OrientationRequested[3];
717 orSup[0] = OrientationRequested.PORTRAIT;
718 orSup[1] = OrientationRequested.LANDSCAPE;
719 orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
720 return orSup;
721 }
722 } else {
723 return orientSup;
724 }
725 } else if (category == PageRanges.class) {
726 if (flavor == null ||
727 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
728 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
729 PageRanges []arr = new PageRanges[1];
730 arr[0] = new PageRanges(1, Integer.MAX_VALUE);
731 return arr;
732 } else {
733
734 return null;
735 }
736 } else if (category == RequestingUserName.class) {
737 String userName = "";
738 try {
739 userName = System.getProperty("user.name", "");
740 } catch (SecurityException se) {
741 }
742 return new RequestingUserName(userName, null);
743 } else if (category == Sides.class) {
744
745
746
747
748
749 AttributeClass attribClass = (getAttMap != null) ?
750 (AttributeClass)getAttMap.get("sides-supported")
751 : null;
752 if (attribClass != null) {
753 String[] sidesArray = attribClass.getArrayOfStringValues();
754 if ((sidesArray != null) && (sidesArray.length > 0)) {
755 Sides[] sidesSup = new Sides[sidesArray.length];
756 for (int i=0; i<sidesArray.length; i++) {
757 if (sidesArray[i].endsWith("long-edge")) {
758 sidesSup[i] = Sides.TWO_SIDED_LONG_EDGE;
759 } else if (sidesArray[i].endsWith("short-edge")) {
760 sidesSup[i] = Sides.TWO_SIDED_SHORT_EDGE;
761 } else {
762 sidesSup[i] = Sides.ONE_SIDED;
763 }
764 }
765 return sidesSup;
766 }
767 }
768 }
769
770 return null;
771 }
772
773
774 private class ExtFinishing extends Finishings {
775 ExtFinishing(int value) {
776 super(100);
777 }
778
779 EnumSyntax[] getAll() {
780 EnumSyntax[] es = super.getEnumValueTable();
781 return es;
782 }
783 }
784
785
786 public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
787 AttributeSet attributes) {
788 if (flavor != null && !isDocFlavorSupported(flavor)) {
789 throw new IllegalArgumentException("flavor " + flavor +
790 "is not supported");
791 }
792
793 if (attributes == null) {
794 return null;
795 }
796
797 Attribute attr;
798 AttributeSet unsupp = new HashAttributeSet();
799 Attribute []attrs = attributes.toArray();
800 for (int i=0; i<attrs.length; i++) {
801 try {
802 attr = attrs[i];
803 if (!isAttributeCategorySupported(attr.getCategory())) {
804 unsupp.add(attr);
805 } else if (!isAttributeValueSupported(attr, flavor,
806 attributes)) {
807 unsupp.add(attr);
808 }
809 } catch (ClassCastException e) {
810 }
811 }
812 if (unsupp.isEmpty()) {
813 return null;
814 } else {
815 return unsupp;
816 }
817 }
818
819
820 public synchronized DocFlavor[] getSupportedDocFlavors() {
821
822 if (supportedDocFlavors != null) {
823 int len = supportedDocFlavors.length;
824 DocFlavor[] copyflavors = new DocFlavor[len];
825 System.arraycopy(supportedDocFlavors, 0, copyflavors, 0, len);
826 return copyflavors;
827 }
828 initAttributes();
829
830 if ((getAttMap != null) &&
831 getAttMap.containsKey("document-format-supported")) {
832
833 AttributeClass attribClass =
834 (AttributeClass)getAttMap.get("document-format-supported");
835 if (attribClass != null) {
836 String mimeType;
837 boolean psSupported = false;
838 String[] docFlavors = attribClass.getArrayOfStringValues();
839 DocFlavor[] flavors;
840 HashSet docList = new HashSet();
841 int j;
842 String hostEnc = DocFlavor.hostEncoding.
843 toLowerCase(Locale.ENGLISH);
844 boolean addHostEncoding = !hostEnc.equals("utf-8") &&
845 !hostEnc.equals("utf-16") && !hostEnc.equals("utf-16be") &&
846 !hostEnc.equals("utf-16le") && !hostEnc.equals("us-ascii");
847
848 for (int i = 0; i < docFlavors.length; i++) {
849 for (j=0; j<allDocFlavors.length; j++) {
850 flavors = (DocFlavor[])allDocFlavors[j];
851
852 mimeType = flavors[0].getMimeType();
853 if (mimeType.startsWith(docFlavors[i])) {
854
855 docList.addAll(Arrays.asList(flavors));
856
857 if (mimeType.equals("text/plain") &&
858 addHostEncoding) {
859 docList.add(Arrays.asList(textPlainHost));
860 } else if (mimeType.equals("text/html") &&
861 addHostEncoding) {
862 docList.add(Arrays.asList(textHtmlHost));
863 } else if (mimeType.equals("image/png")) {
864 pngImagesAdded = true;
865 } else if (mimeType.equals("image/gif")) {
866 gifImagesAdded = true;
867 } else if (mimeType.equals("image/jpeg")) {
868 jpgImagesAdded = true;
869 } else if (mimeType.indexOf("postscript") != -1) {
870 psSupported = true;
871 }
872 break;
873 }
874 }
875
876
877 if (j == allDocFlavors.length) {
878
879 docList.add(new DocFlavor.BYTE_ARRAY(docFlavors[i]));
880 docList.add(new DocFlavor.INPUT_STREAM(docFlavors[i]));
881 docList.add(new DocFlavor.URL(docFlavors[i]));
882 }
883 }
884
885
886
887 if (psSupported || isCupsPrinter) {
888
889
890
891
892
893 docList.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE);
894 docList.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
895
896 docList.addAll(Arrays.asList(imageJPG));
897 docList.addAll(Arrays.asList(imagePNG));
898 docList.addAll(Arrays.asList(imageGIF));
899 }
900 supportedDocFlavors = new DocFlavor[docList.size()];
901 docList.toArray(supportedDocFlavors);
902 int len = supportedDocFlavors.length;
903 DocFlavor[] copyflavors = new DocFlavor[len];
904 System.arraycopy(supportedDocFlavors, 0, copyflavors, 0, len);
905 return copyflavors;
906 }
907 }
908 return null;
909 }
910
911
912 public boolean isDocFlavorSupported(DocFlavor flavor) {
913 if (supportedDocFlavors == null) {
914 getSupportedDocFlavors();
915 }
916 if (supportedDocFlavors != null) {
917 for (int f=0; f<supportedDocFlavors.length; f++) {
918 if (flavor.equals(supportedDocFlavors[f])) {
919 return true;
920 }
921 }
922 }
923 return false;
924 }
925
926
927
928
929
930 public CustomMediaSizeName findCustomMedia(MediaSizeName media) {
931 if (customMediaSizeNames == null) {
932 return null;
933 }
934 for (int i=0; i< customMediaSizeNames.length; i++) {
935 CustomMediaSizeName custom =
936 (CustomMediaSizeName)customMediaSizeNames[i];
937 MediaSizeName msn = custom.getStandardMedia();
938 if (media.equals(msn)) {
939 return customMediaSizeNames[i];
940 }
941 }
942 return null;
943 }
944
945
946
947
948
949 private Media getIPPMedia(String mediaName) {
950 CustomMediaSizeName sampleSize = new CustomMediaSizeName("sample", "",
951 0, 0);
952 Media[] sizes = sampleSize.getSuperEnumTable();
953 for (int i=0; i<sizes.length; i++) {
954 if (mediaName.equals(""+sizes[i])) {
955 return sizes[i];
956 }
957 }
958 CustomMediaTray sampleTray = new CustomMediaTray("sample", "");
959 Media[] trays = sampleTray.getSuperEnumTable();
960 for (int i=0; i<trays.length; i++) {
961 if (mediaName.equals(""+trays[i])) {
962 return trays[i];
963 }
964 }
965 return null;
966 }
967
968 private Media[] getSupportedMedia() {
969 if ((getAttMap != null) &&
970 getAttMap.containsKey("media-supported")) {
971
972 AttributeClass attribClass =
973 (AttributeClass)getAttMap.get("media-supported");
974
975 if (attribClass != null) {
976 String[] mediaVals = attribClass.getArrayOfStringValues();
977 Media msn;
978 Media[] mediaNames =
979 new Media[mediaVals.length];
980 for (int i=0; i<mediaVals.length; i++) {
981 msn = getIPPMedia(mediaVals[i]);
982
983 mediaNames[i] = msn;
984 }
985 return mediaNames;
986 }
987 }
988 return new Media[0];
989 }
990
991
992 public synchronized Class[] getSupportedAttributeCategories() {
993 if (supportedCats != null) {
994 return supportedCats;
995 }
996
997 initAttributes();
998
999 ArrayList catList = new ArrayList();
1000 Class cl;
1001
1002 for (int i=0; i < printReqAttribDefault.length; i++) {
1003 PrintRequestAttribute pra =
1004 (PrintRequestAttribute)printReqAttribDefault[i];
1005 if (getAttMap != null &&
1006 getAttMap.containsKey(pra.getName()+"-supported")) {
1007 cl = pra.getCategory();
1008 catList.add(cl);
1009 }
1010 }
1011
1012
1013
1014
1015 if (isCupsPrinter) {
1016 if (!catList.contains(Media.class)) {
1017 catList.add(Media.class);
1018 }
1019
1020
1021
1022 catList.add(MediaPrintableArea.class);
1023
1024
1025 catList.add(Destination.class);
1026 }
1027
1028
1029
1030 if (getAttMap != null && getAttMap.containsKey("color-supported")) {
1031 catList.add(Chromaticity.class);
1032 }
1033 supportedCats = new Class[catList.size()];
1034 catList.toArray(supportedCats);
1035 return supportedCats;
1036 }
1037
1038
1039 public boolean
1040 isAttributeCategorySupported(Class<? extends Attribute> category)
1041 {
1042 if (category == null) {
1043 throw new NullPointerException("null category");
1044 }
1045 if (!(Attribute.class.isAssignableFrom(category))) {
1046 throw new IllegalArgumentException(category +
1047 " is not an Attribute");
1048 }
1049
1050 if (supportedCats == null) {
1051 getSupportedAttributeCategories();
1052 }
1053
1054
1055
1056
1057
1058 if (category == OrientationRequested.class) {
1059 return true;
1060 }
1061
1062 for (int i=0;i<supportedCats.length;i++) {
1063 if (category == supportedCats[i]) {
1064 return true;
1065 }
1066 }
1067
1068 return false;
1069 }
1070
1071
1072 public synchronized <T extends PrintServiceAttribute>
1073 T getAttribute(Class<T> category)
1074 {
1075 if (category == null) {
1076 throw new NullPointerException("category");
1077 }
1078 if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {
1079 throw new IllegalArgumentException("Not a PrintServiceAttribute");
1080 }
1081
1082 initAttributes();
1083
1084 if (category == PrinterName.class) {
1085 return (T)(new PrinterName(printer, null));
1086 } else if (category == QueuedJobCount.class) {
1087 QueuedJobCount qjc = new QueuedJobCount(0);
1088 AttributeClass ac = (getAttMap != null) ?
1089 (AttributeClass)getAttMap.get(qjc.getName())
1090 : null;
1091 if (ac != null) {
1092 qjc = new QueuedJobCount(ac.getIntValue());
1093 }
1094 return (T)qjc;
1095 } else if (category == PrinterIsAcceptingJobs.class) {
1096 PrinterIsAcceptingJobs accJob =
1097 PrinterIsAcceptingJobs.ACCEPTING_JOBS;
1098 AttributeClass ac = (getAttMap != null) ?
1099 (AttributeClass)getAttMap.get(accJob.getName())
1100 : null;
1101 if ((ac != null) && (ac.getByteValue() == 0)) {
1102 accJob = PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
1103 }
1104 return (T)accJob;
1105 } else if (category == ColorSupported.class) {
1106 ColorSupported cs = ColorSupported.SUPPORTED;
1107 AttributeClass ac = (getAttMap != null) ?
1108 (AttributeClass)getAttMap.get(cs.getName())
1109 : null;
1110 if ((ac != null) && (ac.getByteValue() == 0)) {
1111 cs = ColorSupported.NOT_SUPPORTED;
1112 }
1113 return (T)cs;
1114 } else if (category == PDLOverrideSupported.class) {
1115
1116 if (isCupsPrinter) {
1117
1118 return (T)PDLOverrideSupported.NOT_ATTEMPTED;
1119 } else {
1120
1121 return (T)PDLOverrideSupported.NOT_ATTEMPTED;
1122 }
1123 } else {
1124 return null;
1125 }
1126 }
1127
1128
1129 public synchronized PrintServiceAttributeSet getAttributes() {
1130
1131 init = false;
1132 initAttributes();
1133
1134 HashPrintServiceAttributeSet attrs =
1135 new HashPrintServiceAttributeSet();
1136
1137 for (int i=0; i < serviceAttributes.length; i++) {
1138 String name = (String)serviceAttributes[i][1];
1139 if (getAttMap != null && getAttMap.containsKey(name)) {
1140 Class c = (Class)serviceAttributes[i][0];
1141 PrintServiceAttribute psa = getAttribute(c);
1142 if (psa != null) {
1143 attrs.add(psa);
1144 }
1145 }
1146 }
1147 return AttributeSetUtilities.unmodifiableView(attrs);
1148 }
1149
1150 public boolean isIPPSupportedImages(String mimeType) {
1151 if (supportedDocFlavors == null) {
1152 getSupportedDocFlavors();
1153 }
1154
1155 if (mimeType.equals("image/png") && pngImagesAdded) {
1156 return true;
1157 } else if (mimeType.equals("image/gif") && gifImagesAdded) {
1158 return true;
1159 } else if (mimeType.equals("image/jpeg") && jpgImagesAdded) {
1160 return true;
1161 }
1162
1163 return false;
1164 }
1165
1166
1167 private boolean isSupportedCopies(Copies copies) {
1168 CopiesSupported cs = (CopiesSupported)
1169 getSupportedAttributeValues(Copies.class, null, null);
1170 int[][] members = cs.getMembers();
1171 int min, max;
1172 if ((members.length > 0) && (members[0].length > 0)) {
1173 min = members[0][0];
1174 max = members[0][1];
1175 } else {
1176 min = 1;
1177 max = MAXCOPIES;
1178 }
1179
1180 int value = copies.getValue();
1181 return (value >= min && value <= max);
1182 }
1183
1184 private boolean isAutoSense(DocFlavor flavor) {
1185 if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) ||
1186 flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) ||
1187 flavor.equals(DocFlavor.URL.AUTOSENSE)) {
1188 return true;
1189 }
1190 else {
1191 return false;
1192 }
1193 }
1194
1195 private synchronized boolean isSupportedMediaTray(MediaTray msn) {
1196 initAttributes();
1197
1198 if (mediaTrays != null) {
1199 for (int i=0; i<mediaTrays.length; i++) {
1200 if (msn.equals(mediaTrays[i])) {
1201 return true;
1202 }
1203 }
1204 }
1205 return false;
1206 }
1207
1208 private synchronized boolean isSupportedMedia(MediaSizeName msn) {
1209 initAttributes();
1210
1211 if (msn.equals((Media)getDefaultAttributeValue(Media.class))) {
1212 return true;
1213 }
1214 for (int i=0; i<mediaSizeNames.length; i++) {
1215 debug_println(debugPrefix+"isSupportedMedia, mediaSizeNames[i] "+mediaSizeNames[i]);
1216 if (msn.equals(mediaSizeNames[i])) {
1217 return true;
1218 }
1219 }
1220 return false;
1221 }
1222
1223
1224
1225
1226 private boolean
1227 isDestinationSupported(DocFlavor flavor, AttributeSet attributes) {
1228
1229 if ((attributes != null) &&
1230 (attributes.get(Destination.class) != null) &&
1231 !(flavor == null ||
1232 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1233 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1234 return false;
1235 }
1236 return true;
1237 }
1238
1239
1240 public boolean isAttributeValueSupported(Attribute attr,
1241 DocFlavor flavor,
1242 AttributeSet attributes) {
1243 if (attr == null) {
1244 throw new NullPointerException("null attribute");
1245 }
1246 if (flavor != null) {
1247 if (!isDocFlavorSupported(flavor)) {
1248 throw new IllegalArgumentException(flavor +
1249 " is an unsupported flavor");
1250 } else if (isAutoSense(flavor)) {
1251 return false;
1252 }
1253 }
1254 Class category = attr.getCategory();
1255 if (!isAttributeCategorySupported(category)) {
1256 return false;
1257 }
1258
1259
1260 if (!isDestinationSupported(flavor, attributes)) {
1261 return false;
1262 }
1263
1264
1265 if (attr.getCategory() == Chromaticity.class) {
1266 if ((flavor == null) ||
1267 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1268 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1269 !isIPPSupportedImages(flavor.getMimeType())) {
1270 return attr == Chromaticity.COLOR;
1271 } else {
1272 return false;
1273 }
1274 } else if (attr.getCategory() == Copies.class) {
1275 return (flavor == null ||
1276 !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
1277 flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
1278 flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) &&
1279 isSupportedCopies((Copies)attr);
1280
1281 } else if (attr.getCategory() == Destination.class) {
1282 if (flavor == null ||
1283 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1284 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
1285 URI uri = ((Destination)attr).getURI();
1286 if ("file".equals(uri.getScheme()) &&
1287 !(uri.getSchemeSpecificPart().equals(""))) {
1288 return true;
1289 }
1290 }
1291 return false;
1292 } else if (attr.getCategory() == Media.class) {
1293 if (attr instanceof MediaSizeName) {
1294 return isSupportedMedia((MediaSizeName)attr);
1295 }
1296 if (attr instanceof MediaTray) {
1297 return isSupportedMediaTray((MediaTray)attr);
1298 }
1299 } else if (attr.getCategory() == PageRanges.class) {
1300 if (flavor != null &&
1301 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1302 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1303 return false;
1304 }
1305 } else if (attr.getCategory() == SheetCollate.class) {
1306 if (flavor != null &&
1307 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1308 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1309 return false;
1310 }
1311 } else if (attr.getCategory() == Sides.class) {
1312 Sides[] sidesArray = (Sides[])getSupportedAttributeValues(
1313 Sides.class,
1314 flavor,
1315 attributes);
1316
1317 if (sidesArray != null) {
1318 for (int i=0; i<sidesArray.length; i++) {
1319 if (sidesArray[i] == (Sides)attr) {
1320 return true;
1321 }
1322 }
1323 }
1324 return false;
1325 } else if (attr.getCategory() == OrientationRequested.class) {
1326 OrientationRequested[] orientArray =
1327 (OrientationRequested[])getSupportedAttributeValues(
1328 OrientationRequested.class,
1329 flavor,
1330 attributes);
1331
1332 if (orientArray != null) {
1333 for (int i=0; i<orientArray.length; i++) {
1334 if (orientArray[i] == (OrientationRequested)attr) {
1335 return true;
1336 }
1337 }
1338 }
1339 return false;
1340 }
1341 return true;
1342 }
1343
1344
1345 public synchronized Object
1346 getDefaultAttributeValue(Class<? extends Attribute> category)
1347 {
1348 if (category == null) {
1349 throw new NullPointerException("null category");
1350 }
1351 if (!Attribute.class.isAssignableFrom(category)) {
1352 throw new IllegalArgumentException(category +
1353 " is not an Attribute");
1354 }
1355 if (!isAttributeCategorySupported(category)) {
1356 return null;
1357 }
1358
1359 initAttributes();
1360
1361 String catName = null;
1362 for (int i=0; i < printReqAttribDefault.length; i++) {
1363 PrintRequestAttribute pra =
1364 (PrintRequestAttribute)printReqAttribDefault[i];
1365 if (pra.getCategory() == category) {
1366 catName = pra.getName();
1367 break;
1368 }
1369 }
1370 String attribName = catName+"-default";
1371 AttributeClass attribClass = (getAttMap != null) ?
1372 (AttributeClass)getAttMap.get(attribName) : null;
1373
1374 if (category == Copies.class) {
1375 if (attribClass != null) {
1376 return new Copies(attribClass.getIntValue());
1377 } else {
1378 return new Copies(1);
1379 }
1380 } else if (category == Chromaticity.class) {
1381 return Chromaticity.COLOR;
1382 } else if (category == Destination.class) {
1383 try {
1384 return new Destination((new File("out.ps")).toURI());
1385 } catch (SecurityException se) {
1386 try {
1387 return new Destination(new URI("file:out.ps"));
1388 } catch (URISyntaxException e) {
1389 return null;
1390 }
1391 }
1392 } else if (category == Fidelity.class) {
1393 return Fidelity.FIDELITY_FALSE;
1394 } else if (category == Finishings.class) {
1395 return Finishings.NONE;
1396 } else if (category == JobName.class) {
1397 return new JobName("Java Printing", null);
1398 } else if (category == JobSheets.class) {
1399 if (attribClass != null &&
1400 attribClass.getStringValue().equals("none")) {
1401 return JobSheets.NONE;
1402 } else {
1403 return JobSheets.STANDARD;
1404 }
1405 } else if (category == Media.class) {
1406 defaultMediaIndex = 0;
1407 if (mediaSizeNames.length == 0) {
1408 String defaultCountry = Locale.getDefault().getCountry();
1409 if (defaultCountry != null &&
1410 (defaultCountry.equals("") ||
1411 defaultCountry.equals(Locale.US.getCountry()) ||
1412 defaultCountry.equals(Locale.CANADA.getCountry()))) {
1413 return MediaSizeName.NA_LETTER;
1414 } else {
1415 return MediaSizeName.ISO_A4;
1416 }
1417 }
1418
1419 if (attribClass != null) {
1420 String name = attribClass.getStringValue();
1421 if (isCupsPrinter) {
1422 for (int i=0; i< customMediaSizeNames.length; i++) {
1423
1424
1425
1426
1427 if (customMediaSizeNames[i].toString().indexOf(name)
1428 != -1) {
1429 defaultMediaIndex = i;
1430 return mediaSizeNames[defaultMediaIndex];
1431 }
1432 }
1433 } else {
1434 for (int i=0; i< mediaSizeNames.length; i++) {
1435 if (mediaSizeNames[i].toString().indexOf(name) != -1) {
1436 defaultMediaIndex = i;
1437 return mediaSizeNames[defaultMediaIndex];
1438 }
1439 }
1440 }
1441 }
1442 return mediaSizeNames[defaultMediaIndex];
1443
1444 } else if (category == MediaPrintableArea.class) {
1445 MediaPrintableArea[] mpas;
1446 if ((cps != null) &&
1447 ((mpas = cps.getMediaPrintableArea()) != null)) {
1448 if (defaultMediaIndex == -1) {
1449
1450 getDefaultAttributeValue(Media.class);
1451 }
1452 return mpas[defaultMediaIndex];
1453 } else {
1454 String defaultCountry = Locale.getDefault().getCountry();
1455 float iw, ih;
1456 if (defaultCountry != null &&
1457 (defaultCountry.equals("") ||
1458 defaultCountry.equals(Locale.US.getCountry()) ||
1459 defaultCountry.equals(Locale.CANADA.getCountry()))) {
1460 iw = MediaSize.NA.LETTER.getX(Size2DSyntax.INCH) - 0.5f;
1461 ih = MediaSize.NA.LETTER.getY(Size2DSyntax.INCH) - 0.5f;
1462 } else {
1463 iw = MediaSize.ISO.A4.getX(Size2DSyntax.INCH) - 0.5f;
1464 ih = MediaSize.ISO.A4.getY(Size2DSyntax.INCH) - 0.5f;
1465 }
1466 return new MediaPrintableArea(0.25f, 0.25f, iw, ih,
1467 MediaPrintableArea.INCH);
1468 }
1469 } else if (category == NumberUp.class) {
1470 return new NumberUp(1);
1471 } else if (category == OrientationRequested.class) {
1472 if (attribClass != null) {
1473 switch (attribClass.getIntValue()) {
1474 default:
1475 case 3: return OrientationRequested.PORTRAIT;
1476 case 4: return OrientationRequested.LANDSCAPE;
1477 case 5: return OrientationRequested.REVERSE_LANDSCAPE;
1478 case 6: return OrientationRequested.REVERSE_PORTRAIT;
1479 }
1480 } else {
1481 return OrientationRequested.PORTRAIT;
1482 }
1483 } else if (category == PageRanges.class) {
1484 if (attribClass != null) {
1485 int[] range = attribClass.getIntRangeValue();
1486 return new PageRanges(range[0], range[1]);
1487 } else {
1488 return new PageRanges(1, Integer.MAX_VALUE);
1489 }
1490 } else if (category == RequestingUserName.class) {
1491 String userName = "";
1492 try {
1493 userName = System.getProperty("user.name", "");
1494 } catch (SecurityException se) {
1495 }
1496 return new RequestingUserName(userName, null);
1497 } else if (category == SheetCollate.class) {
1498 return SheetCollate.UNCOLLATED;
1499 } else if (category == Sides.class) {
1500 if (attribClass != null) {
1501 if (attribClass.getStringValue().endsWith("long-edge")) {
1502 return Sides.TWO_SIDED_LONG_EDGE;
1503 } else if (attribClass.getStringValue().endsWith(
1504 "short-edge")) {
1505 return Sides.TWO_SIDED_SHORT_EDGE;
1506 }
1507 }
1508 return Sides.ONE_SIDED;
1509 }
1510
1511 return null;
1512 }
1513
1514 public ServiceUIFactory getServiceUIFactory() {
1515 return null;
1516 }
1517
1518 public void wakeNotifier() {
1519 synchronized (this) {
1520 if (notifier != null) {
1521 notifier.wake();
1522 }
1523 }
1524 }
1525
1526 public void addPrintServiceAttributeListener(
1527 PrintServiceAttributeListener listener) {
1528 synchronized (this) {
1529 if (listener == null) {
1530 return;
1531 }
1532 if (notifier == null) {
1533 notifier = new ServiceNotifier(this);
1534 }
1535 notifier.addListener(listener);
1536 }
1537 }
1538
1539 public void removePrintServiceAttributeListener(
1540 PrintServiceAttributeListener listener) {
1541 synchronized (this) {
1542 if (listener == null || notifier == null ) {
1543 return;
1544 }
1545 notifier.removeListener(listener);
1546 if (notifier.isEmpty()) {
1547 notifier.stopNotifier();
1548 notifier = null;
1549 }
1550 }
1551 }
1552
1553 public String getName() {
1554 return printer;
1555 }
1556
1557
1558 public boolean usesClass(Class c) {
1559 return (c == sun.print.PSPrinterJob.class);
1560 }
1561
1562
1563 public static HttpURLConnection getIPPConnection(URL url) {
1564 HttpURLConnection connection;
1565 try {
1566 connection = (HttpURLConnection)url.openConnection();
1567 } catch (java.io.IOException ioe) {
1568 return null;
1569 }
1570 if (!(connection instanceof HttpURLConnection)) {
1571 return null;
1572 }
1573 connection.setUseCaches(false);
1574 connection.setDefaultUseCaches(false);
1575 connection.setDoInput(true);
1576 connection.setDoOutput(true);
1577 connection.setRequestProperty("Content-type", "application/ipp");
1578 return connection;
1579 }
1580
1581
1582 public synchronized boolean isPostscript() {
1583 if (isPS == null) {
1584 isPS = Boolean.TRUE;
1585 if (isCupsPrinter) {
1586 try {
1587 urlConnection = getIPPConnection(
1588 new URL(myURL+".ppd"));
1589
1590 InputStream is = urlConnection.getInputStream();
1591 if (is != null) {
1592 BufferedReader d =
1593 new BufferedReader(new InputStreamReader(is,
1594 Charset.forName("ISO-8859-1")));
1595 String lineStr;
1596 while ((lineStr = d.readLine()) != null) {
1597 if (lineStr.startsWith("*cupsFilter:")) {
1598 isPS = Boolean.FALSE;
1599 break;
1600 }
1601 }
1602 }
1603 } catch (java.io.IOException e) {
1604 debug_println(" isPostscript, e= "+e);
1605
1606
1607
1608
1609 }
1610 }
1611 }
1612 return isPS.booleanValue();
1613 }
1614
1615
1616 private void opGetAttributes() {
1617 try {
1618 debug_println(debugPrefix+"opGetAttributes myURI "+myURI+" myURL "+myURL);
1619
1620 AttributeClass attClNoUri[] = {
1621 AttributeClass.ATTRIBUTES_CHARSET,
1622 AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE};
1623
1624 AttributeClass attCl[] = {
1625 AttributeClass.ATTRIBUTES_CHARSET,
1626 AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
1627 new AttributeClass("printer-uri",
1628 AttributeClass.TAG_URI,
1629 ""+myURI)};
1630
1631 OutputStream os = (OutputStream)java.security.AccessController.
1632 doPrivileged(new java.security.PrivilegedAction() {
1633 public Object run() {
1634 try {
1635 return urlConnection.getOutputStream();
1636 } catch (Exception e) {
1637 }
1638 return null;
1639 }
1640 });
1641
1642 if (os == null) {
1643 return;
1644 }
1645
1646 boolean success = (myURI == null) ?
1647 writeIPPRequest(os, OP_GET_ATTRIBUTES, attClNoUri) :
1648 writeIPPRequest(os, OP_GET_ATTRIBUTES, attCl);
1649 if (success) {
1650 InputStream is = null;
1651 if ((is = urlConnection.getInputStream())!=null) {
1652 HashMap[] responseMap = readIPPResponse(is);
1653
1654 if (responseMap != null && responseMap.length > 0) {
1655 getAttMap = responseMap[0];
1656 }
1657 } else {
1658 debug_println(debugPrefix+"opGetAttributes - null input stream");
1659 }
1660 is.close();
1661 }
1662 os.close();
1663 } catch (java.io.IOException e) {
1664 debug_println(debugPrefix+"opGetAttributes - input/output stream: "+e);
1665 }
1666 }
1667
1668
1669 public static boolean writeIPPRequest(OutputStream os,
1670 String operCode,
1671 AttributeClass[] attCl) {
1672 OutputStreamWriter osw;
1673 try {
1674 osw = new OutputStreamWriter(os, "UTF-8");
1675 } catch (java.io.UnsupportedEncodingException exc) {
1676 debug_println(debugPrefix+"writeIPPRequest, UTF-8 not supported? Exception: "+exc);
1677 return false;
1678 }
1679 debug_println(debugPrefix+"writeIPPRequest, op code= "+operCode);
1680 char[] opCode = new char[2];
1681 opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16);
1682 opCode[1] = (char)Byte.parseByte(operCode.substring(2,4), 16);
1683 char[] bytes = {0x01, 0x01, 0x00, 0x01};
1684 try {
1685 osw.write(bytes, 0, 2);
1686 osw.write(opCode, 0, 2);
1687 bytes[0] = 0x00; bytes[1] = 0x00;
1688 osw.write(bytes, 0, 4);
1689
1690 bytes[0] = 0x01;
1691 osw.write(bytes[0]);
1692
1693 String valStr;
1694 char[] lenStr;
1695
1696 AttributeClass ac;
1697 for (int i=0; i < attCl.length; i++) {
1698 ac = attCl[i];
1699 osw.write(ac.getType());
1700
1701 lenStr = ac.getLenChars();
1702 osw.write(lenStr, 0, 2);
1703 osw.write(""+ac, 0, ac.getName().length());
1704
1705
1706 if (ac.getType() >= AttributeClass.TAG_TEXT_LANGUAGE &&
1707 ac.getType() <= AttributeClass.TAG_MIME_MEDIATYPE){
1708 valStr = (String)ac.getObjectValue();
1709 bytes[0] = 0; bytes[1] = (char)valStr.length();
1710 osw.write(bytes, 0, 2);
1711 osw.write(valStr, 0, valStr.length());
1712 }
1713
1714 }
1715
1716 osw.write(GRPTAG_END_ATTRIBUTES);
1717 osw.flush();
1718 osw.close();
1719 } catch (java.io.IOException ioe) {
1720 debug_println(debugPrefix+"writeIPPRequest, IPPPrintService Exception in writeIPPRequest: "+ioe);
1721 return false;
1722 }
1723 return true;
1724 }
1725
1726
1727 public static HashMap[] readIPPResponse(InputStream inputStream) {
1728
1729 if (inputStream == null) {
1730 return null;
1731 }
1732
1733 byte response[] = new byte[MAX_ATTRIBUTE_LENGTH];
1734 try {
1735
1736 DataInputStream ois = new DataInputStream(inputStream);
1737
1738
1739 if ((ois.read(response, 0, 8) > -1) &&
1740 (response[2] == STATUSCODE_SUCCESS)) {
1741
1742 ByteArrayOutputStream outObj;
1743 int counter=0;
1744 short len = 0;
1745 String attribStr = null;
1746
1747 byte valTagByte = AttributeClass.TAG_KEYWORD;
1748 ArrayList respList = new ArrayList();
1749 HashMap responseMap = new HashMap();
1750
1751 response[0] = ois.readByte();
1752
1753
1754 while ((response[0] >= GRPTAG_OP_ATTRIBUTES) &&
1755 (response[0] <= GRPTAG_PRINTER_ATTRIBUTES)
1756 && (response[0] != GRPTAG_END_ATTRIBUTES)) {
1757 debug_println(debugPrefix+"readIPPResponse, checking group tag, response[0]= "+
1758 response[0]);
1759
1760 outObj = new ByteArrayOutputStream();
1761
1762 counter = 0;
1763 attribStr = null;
1764
1765
1766 response[0] = ois.readByte();
1767 while (response[0] >= AttributeClass.TAG_UNSUPPORTED_VALUE &&
1768 response[0] <= AttributeClass.TAG_MEMBER_ATTRNAME) {
1769
1770 len = ois.readShort();
1771
1772
1773
1774
1775 if ((len != 0) && (attribStr != null)) {
1776
1777 outObj.write(counter);
1778 outObj.flush();
1779 outObj.close();
1780 byte outArray[] = outObj.toByteArray();
1781
1782
1783 if (responseMap.containsKey(attribStr)) {
1784 respList.add(responseMap);
1785 responseMap = new HashMap();
1786 }
1787
1788
1789 if (valTagByte >= AttributeClass.TAG_INT) {
1790 AttributeClass ac =
1791 new AttributeClass(attribStr,
1792 valTagByte,
1793 outArray);
1794
1795 responseMap.put(ac.getName(), ac);
1796 debug_println(debugPrefix+ "readIPPResponse "+ac);
1797 }
1798
1799 outObj = new ByteArrayOutputStream();
1800 counter = 0;
1801 }
1802
1803 if (counter == 0) {
1804 valTagByte = response[0];
1805 }
1806
1807 if (len != 0) {
1808
1809
1810 if (len > MAX_ATTRIBUTE_LENGTH) {
1811 response = new byte[len];
1812 }
1813 ois.read(response, 0, len);
1814 attribStr = new String(response, 0, len);
1815 }
1816
1817 len = ois.readShort();
1818
1819 outObj.write(len);
1820
1821 if (len > MAX_ATTRIBUTE_LENGTH) {
1822 response = new byte[len];
1823 }
1824 ois.read(response, 0, len);
1825
1826 outObj.write(response, 0, len);
1827 counter++;
1828
1829 response[0] = ois.readByte();
1830 }
1831
1832 if (attribStr != null) {
1833 outObj.write(counter);
1834 outObj.flush();
1835 outObj.close();
1836
1837
1838 if ((counter != 0) &&
1839 responseMap.containsKey(attribStr)) {
1840 respList.add(responseMap);
1841 responseMap = new HashMap();
1842 }
1843
1844 byte outArray[] = outObj.toByteArray();
1845
1846 AttributeClass ac =
1847 new AttributeClass(attribStr,
1848 valTagByte,
1849 outArray);
1850 responseMap.put(ac.getName(), ac);
1851 }
1852 }
1853 ois.close();
1854 if ((responseMap != null) && (responseMap.size() > 0)) {
1855 respList.add(responseMap);
1856 }
1857 return (HashMap[])respList.toArray(
1858 new HashMap[respList.size()]);
1859 } else {
1860 debug_println(debugPrefix+
1861 "readIPPResponse client error, IPP status code-"
1862 +Integer.toHexString(response[2])+" & "
1863 +Integer.toHexString(response[3]));
1864 return null;
1865 }
1866
1867 } catch (java.io.IOException e) {
1868 debug_println(debugPrefix+"readIPPResponse: "+e);
1869 if (debugPrint) {
1870 e.printStackTrace();
1871 }
1872 return null;
1873 }
1874 }
1875
1876
1877 public String toString() {
1878 return "IPP Printer : " + getName();
1879 }
1880
1881 public boolean equals(Object obj) {
1882 return (obj == this ||
1883 (obj instanceof IPPPrintService &&
1884 ((IPPPrintService)obj).getName().equals(getName())));
1885 }
1886
1887 public int hashCode() {
1888 return this.getClass().hashCode()+getName().hashCode();
1889 }
1890 }